home *** CD-ROM | disk | FTP | other *** search
- // **********************************************
- // File: BLOCK.CPP
- // Block operations module
-
- #include "muzika.h"
-
- int markBeginStaff = -1, markBeginX; // Staff and X of mark beginning
- int markEndStaff = -1, markEndX; // Staff and X of mark end
-
- // **********************************************
- // MarkBlock marks a block by copying the parameters
- // to the marking variables.
- // To actually reverse-video the marked area
- // is a job of the PaintEditWindow function.
-
- void MarkBlock(int staffFrom, int Xfrom, int staffTo, int Xto)
- {
- Part &p = *((Part *) &melody.part[displayedPart]);
- markBeginStaff = staffFrom/p.multiplicity()*p.multiplicity();
- markBeginX = Xfrom;
- markEndStaff = staffTo/p.multiplicity()*p.multiplicity();
- markEndX = Xto;
- }
-
- // **********************************************
- // UnmarkBlock unmarks a block by setting the marking variables
- // to impossible values.
-
- void UnmarkBlock()
- {
- markBeginStaff = markEndStaff = -1;
- }
-
- // **********************************************
- // CutBlock cuts the marked block to the clipboard.
-
- void CutBlock()
- {
- // Allocate a memory block (initially of 32K) for the cut operation
- GLOBALHANDLE hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DISCARDABLE, 32767);
- char far *clipboardStart = GlobalLock(hMem);
- char far *clipboard = clipboardStart;
- Part &p = *((Part *) &melody.part[displayedPart]);
-
- // Write the marked block size into the clipboard
- *((int far *) clipboard)++ = p.multiplicity();
- *((int far *) clipboard)++ = markEndStaff-markBeginStaff;
- *((int far *) clipboard)++ = markBeginX;
- *((int far *) clipboard)++ = markEndX;
-
- // Write the musical object information into the clipboard
- for (int staffIndex = markBeginStaff;
- staffIndex/p.multiplicity()*p.multiplicity() <= markEndStaff;
- ++staffIndex) {
- Staff &s = *((Staff *) &p.staff[staffIndex]);
-
- // Cut the point objects:
- // do nothing with unmarked objects,
- // then clip and destroy the marked ones.
- // An object writes its own information to the clipboard
- // in the virtual clipOn function.
- for (int objectIndex = 0;
- objectIndex < s.pointObject.number() &&
- staffIndex/p.multiplicity() == markBeginStaff/p.multiplicity() &&
- ((PointObject *) &s.pointObject[objectIndex])->X() < markBeginX;
- ++objectIndex);
- while (objectIndex < s.pointObject.number() &&
- (staffIndex/p.multiplicity() < markEndStaff/p.multiplicity() ||
- ((PointObject *) &s.pointObject[objectIndex])->X() <= markEndX)) {
- ((PointObject *) &s.pointObject[objectIndex])->clipOn((void far *) clipboard);
- s.pointObject.destroy(objectIndex);
- }
-
- // Cut the continuous objects, similarly to the point ones
- for (objectIndex = 0;
- objectIndex < s.continuousObject.number() &&
- staffIndex/p.multiplicity() == markBeginStaff/p.multiplicity() &&
- ((ContinuousObject *) &s.continuousObject[objectIndex])->Xleft() < markBeginX;
- ++objectIndex);
- while (objectIndex < s.continuousObject.number() &&
- (staffIndex/p.multiplicity() < markEndStaff/p.multiplicity() ||
- ((ContinuousObject *) &s.continuousObject[objectIndex])->Xright() <= markEndX)) {
- ((ContinuousObject *) &s.continuousObject[objectIndex])->clipOn((void far *) clipboard);
- s.continuousObject.destroy(objectIndex);
- }
-
- // Put an end-of-staff marker
- *clipboard++ = STAFF;
- }
-
- // Erase the fully marked staves
- if (markEndStaff-markBeginStaff >= 2*p.multiplicity()) {
- int staffDiff = ((Staff *) &p.staff[markEndStaff])->Y()-
- ((Staff *) &p.staff[markBeginStaff+1])->Y();
- for (staffIndex = markBeginStaff+p.multiplicity();
- staffIndex < markEndStaff;
- ++staffIndex)
- p.staff.destroy(staffIndex);
- for (; staffIndex < p.staff.number(); ++staffIndex)
- ((Staff *) &p.staff[staffIndex])->Y() -= staffDiff;
- }
-
- // Unmark the block once the cut operation is finished
- UnmarkBlock();
-
- // Reallocate the 32K block to the actually needed size
- GlobalUnlock(hMem);
- GlobalReAlloc(hMem, clipboard-clipboardStart, 0);
-
- // Set a clipboard handle to point to the cut block information
- OpenClipboard(hMainWnd);
- EmptyClipboard();
- SetClipboardData(CF_PRIVATEFIRST, hMem);
- CloseClipboard();
- }
-
- // **********************************************
- // CopyBlock copies the marked block to the clipboard.
-
- void CopyBlock()
- {
- // Allocate a memory block (initially of 32K) for the copy operation
- GLOBALHANDLE hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_DISCARDABLE, 32767);
- char far *clipboardStart = GlobalLock(hMem);
- char far *clipboard = clipboardStart;
- Part &p = *((Part *) &melody.part[displayedPart]);
-
- // Write the marked block size into the clipboard
- *((int far *) clipboard)++ = p.multiplicity();
- *((int far *) clipboard)++ = markEndStaff-markBeginStaff;
- *((int far *) clipboard)++ = markBeginX;
- *((int far *) clipboard)++ = markEndX;
-
- // Write the musical object information into the clipboard
- for (int staffIndex = markBeginStaff;
- staffIndex/p.multiplicity()*p.multiplicity() <= markEndStaff;
- ++staffIndex) {
- Staff &s = *((Staff *) &p.staff[staffIndex]);
-
- // Clip the point objects.
- // Each object writes its own information
- // in the virtual clipOn function.
- for (int objectIndex = 0; objectIndex < s.pointObject.number();
- ++objectIndex) {
- PointObject &obj = *((PointObject *) &s.pointObject[objectIndex]);
- if ((staffIndex/p.multiplicity() > markBeginStaff/p.multiplicity() ||
- obj.X() >= markBeginX) &&
- (staffIndex/p.multiplicity() < markEndStaff/p.multiplicity() ||
- obj.X() <= markEndX))
- obj.clipOn((void far *) clipboard);
- }
-
- // Clip the continuous objects, similarly to the point ones
- for (objectIndex = 0; objectIndex < s.continuousObject.number();
- ++objectIndex) {
- ContinuousObject &obj =
- *((ContinuousObject *) &s.pointObject[objectIndex]);
- if ((staffIndex/p.multiplicity() > markBeginStaff/p.multiplicity() ||
- obj.Xleft() >= markBeginX) &&
- (staffIndex/p.multiplicity() < markEndStaff/p.multiplicity() ||
- obj.Xright() <= markEndX))
- obj.clipOn((void far *) clipboard);
- }
-
- // Put an end-of-staff marker
- *clipboard++ = STAFF;
- }
-
- // Reallocate the 32K block to the actually needed size
- GlobalUnlock(hMem);
- GlobalReAlloc(hMem, clipboard-clipboardStart, 0);
-
- // Set a clipboard handle to point to the copied block data
- OpenClipboard(hMainWnd);
- EmptyClipboard();
- SetClipboardData(CF_PRIVATEFIRST, hMem);
- CloseClipboard();
- }
-
- // **********************************************
- // PasteBlock pastes the block whose handle is in the clipboard
- // to the given (staff,X) coordinate.
-
- void PasteBlock(int pasteStaff, int pasteX)
- {
- // Obtain a pointer to the clipboard entry
- OpenClipboard(hMainWnd);
- GLOBALHANDLE hMem = GetClipboardData(CF_PRIVATEFIRST);
- if (!hMem)
- return;
- char far *clipboard = GlobalLock(hMem);
- Part &p = *((Part *) &melody.part[displayedPart]);
-
- // Read the block parameters
- if (*((int far *) clipboard)++ != p.multiplicity())
- MessageBox(hEditWnd, "Cannot paste block - different staff multiplicity",
- NULL, MB_OK);
- else {
- // Read the block parameters to variables
- int staffDiff = *((int far *) clipboard)++;
- int beginX = *((int far *) clipboard)++;
- int endX = *((int far *) clipboard)++;
- pasteX = pasteX+endX-beginX < melody.GetStaffWidth() ? pasteX :
- melody.GetStaffWidth()-endX+beginX-1;
- BOOL singleStaffBlock = !staffDiff;
-
- // Paste a single-staff or a multiple-staff block
- // Add the height of the pasted block to all subsequent staves
- for (int index = pasteStaff+p.multiplicity();
- index < p.staff.number(); ++index)
- ((Staff *) &p.staff[index])->Y() += staffDiff*pixelsPerStaff;
-
- // The loop of pasting staves
- staffDiff += p.multiplicity()-1;
- index = pasteStaff;
- int staffY = ((Staff *) &p.staff[index])->Y();
- do {
- // If needed, insert a new staff into the melody
- if (index/p.multiplicity()*p.multiplicity() > pasteStaff)
- p.staff.insertAt(*new Staff(staffY += pixelsPerStaff), index);
- Staff &s = *((Staff *) &p.staff[index]);
- int type;
-
- // As long as the staff end is not reached, paste objects
- while (*clipboard != STAFF) {
- // Create an object from the information in the clipboard
- MusicalObject *m = PasteObject((void far *) clipboard, &type);
- switch (type) {
- case POINTOBJECT:
- // If the block is less than a single staff,
- // adjust the X coordinate of the pasted point object
- int X = ((PointObject *) m)->X();
- X += singleStaffBlock ? pasteX-beginX : 0;
- for (int i = 0;
- i < s.pointObject.number() &&
- ((PointObject *) &s.pointObject[i])->X() <= X;
- ++i);
- // Insert the object into the point object list
- s.pointObject.insertAt(*m, i);
- ((PointObject *) m)->X() = X;
- break;
-
- case CONTINUOUSOBJECT:
- // If the block is less than a single staff,
- // adjust the X coordinates of the pasted continuous object
- X = ((ContinuousObject *) m)->Xleft();
- X += singleStaffBlock ? pasteX-beginX : 0;
- for (i = 0;
- i < s.continuousObject.number() &&
- ((ContinuousObject *) &s.continuousObject[i])->Xleft() <= X;
- ++i);
- // Insert the object into the continuous object list
- s.continuousObject.insertAt(*m, i);
- ((ContinuousObject *) m)->Xright() += X-((ContinuousObject *) m)->Xleft();
- ((ContinuousObject *) m)->Xleft() = X;
- break;
- }
- }
- ++clipboard;
- ++index;
- } while (--staffDiff >= 0);
- }
-
- // Unlock the handle
- GlobalUnlock(hMem);
- }
-